/*
 * Copyright 2011 J. Auer, J. Andert, F.-J. Jendrusch, U. Celebi
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package de.fuberlin.replication.storage.jdbc.sqlite;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Iterator;

import de.fuberlin.replication.library.Metadata;
import de.fuberlin.replication.library.Subset;
import de.fuberlin.replication.library.Version;
import de.fuberlin.replication.storage.MetadataDAO;

/**
 * SQLite {@link Metadata} Data Access Object (DAO).
 */
public class SQLiteMetadataDAO extends SQLiteDAO implements MetadataDAO {

	/**
	 * @param connection SQLite DB connection
	 */
	public SQLiteMetadataDAO(Connection connection) {
		super(connection);
	}

	@Override
	public Iterable<Metadata> getAll() {
		return getAll(null);
	}

	@Override
	public Iterable<Metadata> getAll(Subset subset) {
		Connection conn = getConnection();

		String whereClause = "";

		if (subset != null)
			whereClause = " WHERE subset_id = "
					+ String.valueOf(subset.getId());

		Iterable<Metadata> iterator = null;

		try {
			Statement s = conn.createStatement();
			ResultSet res = s
					.executeQuery("SELECT m.name, m.replica, m.version, m.timestamp "
							+ "FROM metadata m" + whereClause + ";");
			iterator = new SQLiteIterable<Metadata>(new SQLiteMetadataIterator(res).getIterator());
			s.close();
			res.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}

		return iterator;
	}

	@Override
	public Metadata get(String name) {
		Connection conn = getConnection();

		Iterable<Metadata> iterable = null;

		try {
			PreparedStatement prep = conn
					.prepareStatement("SELECT m.name, m.replica, m.version, m.timestamp "
							+ "FROM metadata m WHERE name = ?;");
			prep.setString(1, name);
			ResultSet res = prep.executeQuery();

			iterable = new SQLiteIterable<Metadata>(new SQLiteMetadataIterator(res).getIterator());
			prep.close();
			res.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}

		if (iterable == null)
			return null;

		Iterator<Metadata> iterator = iterable.iterator();

		return (!iterator.hasNext()) ? null : iterator.next();
	}

	@Override
	public void save(Subset subset, Metadata metadata) {
		Connection conn = getConnection();
		Version version = metadata.getVersion();

		try {
			PreparedStatement prep = conn
					.prepareStatement("INSERT INTO metadata (name, subset_id, replica, version, timestamp) VALUES (?, ?, ?, ?, ?)");
			prep.setString(1, metadata.getName());
			prep.setLong(2, Long.valueOf(subset.getId()).longValue());
			prep.setString(3, version.getReplica());
			prep.setLong(4, Long.valueOf(version.getVersion()).longValue());
			prep.setLong(5, Long.valueOf(metadata.getTimestamp()).longValue());
			prep.executeUpdate();

			prep.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void delete(Metadata metadata) {
		Connection conn = getConnection();
		PreparedStatement prep;
		try {
			prep = conn.prepareStatement("DELETE FROM metadata WHERE name = ?");
			prep.setString(1, String.valueOf(metadata.getName()));
			prep.executeUpdate();
			prep.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	@Override
	public long getLatestTimestamp() {
		Connection conn = getConnection();

		try {
			Statement s = conn.createStatement();
			ResultSet res = s.executeQuery("SELECT MAX(timestamp) "
					+ "FROM metadata;");
			long timestamp = res.getLong(1);
			s.close();
			res.close();
			return timestamp;
		} catch (SQLException e) {
			e.printStackTrace();
		}

		return 0;
	}
}